home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / golded / api / dock / main.c < prev    next >
C/C++ Source or Header  |  1995-02-17  |  16KB  |  516 lines

  1. /* -----------------------------------------------------------------------------
  2.  
  3.  GoldED API client example code, ©1995 Dietmar Eilert. Dice:
  4.  
  5.  dcc main.c -// -mRR -r -proto -2.0 -l tmsr.lib -l reqtoolssr.lib -o ram:dock
  6.  
  7.  Note: Compiling this code requires ToolManger includes & ToolManager linker
  8.        libraries. ToolManager is ©1990-1995 Stefan Becker.
  9.  
  10.  The following  example  uses  synchronous  ARexx  communication:  Requests  are
  11.  PutMsg()'ed  to  GoldED's  port,  followed  by a WaitPort() to get the editor's
  12.  response. This works fine since we need no ARexx communication  after  the  API
  13.  link has been established. If there were ARexx communication AFTER the link has
  14.  been established (i.e. after sending the 'API  PORT=...'  command  to  register
  15.  with  GoldED),  we  would  have to use an asynchronous design beeing capable of
  16.  answering incoming API messages while waiting for completion of ARexx  requests
  17.  sent to GoldED.
  18.  
  19.   ------------------------------------------------------------------------------
  20. */
  21.  
  22. /// "includes"
  23.  
  24. #define Prototype extern
  25.  
  26. #include <exec/exec.h>
  27. #include <string.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <dos/dos.h>
  31. #include <dos/rdargs.h>
  32. #include <intuition/intuition.h>
  33. #include <workbench/startup.h>
  34. #include <rexx/errors.h>
  35. #include <rexx/rxslib.h>
  36. #include <libraries/reqtools.h>
  37. #include <utility/tagitem.h>
  38. #include <clib/toolmanager_protos.h>
  39. #include <clib/exec_protos.h>
  40. #include <clib/dos_protos.h>
  41. #include <clib/intuition_protos.h>
  42. #include <clib/rexxsyslib_protos.h>
  43. #include <clib/reqtools_protos.h>
  44.  
  45. #include "golded:api/include/golded.h"
  46.  
  47. // ToolManager objects are a combination of action/image/sound:
  48. // Les objets ToolManager sont une combinaison d'objets action/image/son:
  49.  
  50. struct tmTool {
  51.  
  52.     APTR exec;
  53.     APTR icon;
  54.     APTR sound;
  55. };
  56.  
  57. struct Library *ReqToolsBase;
  58.  
  59. Prototype void   main(int, char **);
  60. Prototype void   HandleAPI(void *, char *, struct TagItem *, UWORD, UWORD);
  61. Prototype ULONG *SendRexxCommand(char *, char *, struct MsgPort *, char *);
  62. Prototype char  *xsprintf(char *, char *);
  63. Prototype struct TagItem *ReadConfig(char *, void *, char *, UWORD *, UWORD *);
  64.  
  65. ///
  66. /// "main"
  67.  
  68. void
  69. main(int argc, char **argv)
  70. {
  71.     const char *version = "$VER: dock 1.6 (" __COMMODORE_DATE__ ")";
  72.  
  73.     struct RDArgs *rdArgs;
  74.  
  75.     ULONG args[] = { 0, 0 };
  76.  
  77.     if (rdArgs = ReadArgs("CONFIG,HOST/K/A", args, NULL)) {
  78.  
  79.         UBYTE *prefs;
  80.         UWORD  try;
  81.         void  *handle;
  82.  
  83.         prefs = args[0] ? (char *)args[0] : "progdir:dock.prefs";
  84.  
  85.         // wait for ToolManager startup
  86.  
  87.         for (try = 20; !(handle = AllocTMHandle()) && try; try--)
  88.             Delay(10);
  89.  
  90.         if (handle) {
  91.  
  92.             struct TagItem *dock;
  93.  
  94.             UWORD dockX = ~0, dockY = ~0;
  95.  
  96.             if (dock = ReadConfig(prefs, handle, (char *)args[1], &dockX, &dockY))
  97.                 HandleAPI(handle, (char *)args[1], dock, dockX, dockY);
  98.  
  99.             FreeTMHandle(handle);
  100.         }
  101.         else
  102.             puts("got no TM handle ?!");
  103.  
  104.         FreeArgs(rdArgs);
  105.     }
  106.     else
  107.         puts("syntax error: dock [<config>] HOST=<host>");
  108.  
  109.     exit(0);
  110. }
  111.  
  112. int
  113. wbmain(struct WBStartup *startup)
  114. {
  115.     if (ReqToolsBase = OpenLibrary("reqtools.library", 37)) {
  116.  
  117.         rtEZRequestTags("No executable - to be used as API client", "OK", NULL, NULL, TAG_DONE);
  118.  
  119.         CloseLibrary(ReqToolsBase);
  120.     }
  121. }
  122.  
  123.  
  124. ///
  125. /// "read config"
  126.  
  127. /* -------------------------------- ReadConfig ---------------------------------
  128.  
  129.  Read config file. Return ready-to-use tag array for dock creation or NULL.
  130.  Write dock screen position to <dockX>/<dockY>.
  131.  
  132. */
  133.  
  134. struct TagItem *
  135. ReadConfig(prefs, handle, host, dockX, dockY)
  136.  
  137. void  *handle;
  138. char  *prefs, *host;
  139. UWORD *dockX, *dockY;
  140. {
  141.     struct TagItem *dock = NULL;
  142.  
  143.     BPTR config;
  144.  
  145.     if (config = Open(prefs, MODE_OLDFILE)) {
  146.  
  147.         struct RDArgs *rdArgs;
  148.  
  149.         if (rdArgs = AllocDosObject(DOS_RDARGS, NULL)) {
  150.  
  151.             static char buffer[256];
  152.  
  153.             UWORD columns, entries, orientation;
  154.  
  155.             columns     = 1;
  156.             orientation = 0;
  157.             entries     = 0;
  158.  
  159.             while (FGets(config, buffer, 255)) {
  160.  
  161.                 char *cmd;
  162.  
  163.                 for (strcat(buffer, "\12"), cmd = buffer; *cmd && (*cmd != ';'); ++cmd) {
  164.  
  165.                     if ((*cmd != ' ') && (*cmd != 10)) {
  166.  
  167.                         ULONG n, argArray[] = { 0, 0, 0, 0, 0, 0 };
  168.  
  169.                         struct RDArgs *args;
  170.  
  171.                         static struct parser { char *command; char *template; } parser[] = {
  172.  
  173.                             "ADD",  "COMMAND/K/A,AREXX/S,EXEC/S,DIR/K,OUTPUT/K,ICON/K/A",
  174.                             "DOCK", "X/N,Y/N,HORIZONTAL/S,COLUMNS/N",
  175.                              NULL
  176.                         };
  177.  
  178.                         for (n = 0; parser[n].command; ++n) {
  179.  
  180.                             if (!memcmp(cmd, parser[n].command, strlen(parser[n].command))) {
  181.  
  182.                                 cmd += strlen(parser[n].command);
  183.  
  184.                                 rdArgs->RDA_Source.CS_Buffer = cmd;
  185.                                 rdArgs->RDA_Source.CS_Length = strlen(cmd);
  186.                                 rdArgs->RDA_Source.CS_CurChr = 0;
  187.                                 rdArgs->RDA_DAList           = NULL;
  188.                                 rdArgs->RDA_Buffer           = NULL;
  189.  
  190.                                 if (args = ReadArgs(parser[n].template, argArray, rdArgs)) {
  191.  
  192.                                     if (n == 0) {
  193.  
  194.                                         char execName[8], iconName[8];
  195.  
  196.                                         struct TagItem iconTags[] = { TMOP_File, strdup((char *)argArray[5]), TMOP_Data, NULL, TAG_DONE };
  197.  
  198.                                         struct TagItem execTags[] = { 
  199.  
  200.                                             TMOP_Command,    xsprintf((char *)argArray[0], host),
  201.                                             TMOP_ExecType,   argArray[1] ? TMET_ARexx : TMET_CLI,
  202.                                             TMOP_Stack,      8192,
  203.                                             TMOP_CurrentDir, argArray[3] ? strdup((char *)argArray[3]) : NULL,
  204.                                             TMOP_Output,     argArray[4] ? strdup((char *)argArray[4]) : NULL,
  205.                                             TAG_DONE
  206.                                         };
  207.  
  208.                                         sprintf(execName, "e%ld", entries);
  209.                                         sprintf(iconName, "i%ld", entries++);
  210.  
  211.                                         CreateTMObjectTagList(handle, strdup(execName), TMOBJTYPE_EXEC,  execTags);
  212.                                         CreateTMObjectTagList(handle, strdup(iconName), TMOBJTYPE_IMAGE, iconTags);
  213.                                     }
  214.  
  215.                                     else if (n == 1) {
  216.  
  217.                                         if (argArray[0])
  218.                                             *dockX = *(ULONG *)argArray[0];
  219.  
  220.                                         if (argArray[1])
  221.                                             *dockY = *(ULONG *)argArray[1];
  222.  
  223.                                         if (argArray[2])
  224.                                             orientation = 1;
  225.  
  226.                                         if (argArray[3])
  227.                                             columns = *(ULONG *)argArray[3];
  228.                                     }
  229.  
  230.                                     FreeArgs(args);
  231.                                 }
  232.                             }
  233.                         }
  234.  
  235.                         break;
  236.                     }
  237.                 }
  238.  
  239.                 if (entries) {
  240.  
  241.                     if (dock = (struct TagItem *)calloc((entries + 9) * sizeof(struct TagItem), 1)) {
  242.  
  243.                         UWORD n;
  244.  
  245.                         dock[0].ti_Tag  = TMOP_PubScreen;
  246.                         dock[1].ti_Tag  = TMOP_LeftEdge;
  247.                         dock[2].ti_Tag  = TMOP_TopEdge;
  248.                         dock[3].ti_Tag  = TMOP_Activated;
  249.                         dock[4].ti_Tag  = TMOP_Centered;
  250.                         dock[5].ti_Tag  = TMOP_Columns;
  251.                         dock[6].ti_Tag  = TMOP_Vertical;
  252.                         dock[7].ti_Tag  = TMOP_Text;
  253.                         dock[8].ti_Tag  = TAG_DONE;
  254.  
  255.                         dock[3].ti_Data = TRUE;
  256.                         dock[5].ti_Data = columns;
  257.                         dock[6].ti_Data = orientation;
  258.  
  259.                         for (n = 0; n < entries; ++n) {
  260.  
  261.                             struct tmTool *tool;
  262.  
  263.                             if (tool = (struct tmTool *)calloc(sizeof(struct tmTool), 1)) {
  264.  
  265.                                 if ((tool->exec = calloc(8, 1)) && (tool->icon = calloc(8, 1))) {
  266.  
  267.                                     sprintf((char *)tool->exec, "e%ld", n);
  268.                                     sprintf((char *)tool->icon, "i%ld", n);
  269.  
  270.                                     dock[8 + n].ti_Tag  = TMOP_Tool;
  271.                                     dock[8 + n].ti_Data = tool;
  272.                                 }
  273.                             }
  274.                         }
  275.                     }
  276.                 }
  277.  
  278.             }
  279.  
  280.             FreeDosObject(DOS_RDARGS, rdArgs);
  281.         }
  282.  
  283.         Close(config);
  284.     }
  285.     else
  286.         puts("dock.prefs missing");
  287.  
  288.     return(dock);
  289. }
  290.  
  291.  
  292. ///
  293. /// "API management"
  294.  
  295. /* --------------------------------- HandleAPI ---------------------------------
  296.  
  297.  Register with GoldED & handle incoming API messages.
  298.  
  299. */
  300.  
  301. void
  302. HandleAPI(handle, host, dock, dockX, dockY)
  303.  
  304. struct TagItem *dock;
  305. char           *host;
  306. void           *handle;
  307. UWORD          dockX, dockY;
  308. {
  309.     struct MsgPort *replyPort;
  310.  
  311.     if (replyPort = CreateMsgPort()) {
  312.  
  313.         char  command[255];
  314.         ULONG *result;
  315.  
  316.         sprintf(command, "API PORT=%ld CLASS=%ld", replyPort, API_CLASS_ROOT | API_CLASS_SCREEN);
  317.  
  318.         if (result = SendRexxCommand(host, command, replyPort, NULL)) {
  319.  
  320.             if (*result == RC_OK) {
  321.  
  322.                 BOOL active = TRUE;
  323.  
  324.                 do {
  325.  
  326.                     struct APIMessage *apiMsg, *nextMsg;
  327.  
  328.                     // API messages might already have arrived since SendRexxCommand() only pulls one message of the port
  329.  
  330.                     while (!(apiMsg = (struct APIMessage *)GetMsg(replyPort)))
  331.                         WaitPort(replyPort);
  332.  
  333.                     do {
  334.  
  335.                         for (nextMsg = apiMsg; nextMsg; nextMsg = nextMsg->api_Next) {
  336.  
  337.                             if (nextMsg->api_State == API_STATE_NOTIFY) {
  338.  
  339.                                 switch (nextMsg->api_Class) {
  340.  
  341.                                     case API_CLASS_ROOT:
  342.  
  343.                                         switch (nextMsg->api_Action) {
  344.  
  345.                                             case API_ACTION_DIE:
  346.  
  347.                                                 active = FALSE;
  348.  
  349.                                                 DeleteTMObject(handle, "dock1");
  350.                                                 break;
  351.  
  352.                                             case API_ACTION_INTRODUCE:
  353.  
  354.                                                 static struct TagItem tags[] = {
  355.  
  356.                                                     API_Client_Name,      "dock",
  357.                                                     API_Client_Copyright, "©1995 Dietmar Eilert",
  358.                                                     API_Client_Purpose,   "ToolManager dock for GoldED",
  359.                                                     TAG_DONE
  360.                                                 };
  361.  
  362.                                                 nextMsg->api_Data = tags;
  363.                                                 break;
  364.  
  365.                                             default:
  366.  
  367.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  368.                                         }
  369.  
  370.                                         break;
  371.  
  372.                                     case API_CLASS_SCREEN:
  373.  
  374.                                         switch (nextMsg->api_Action) {
  375.  
  376.                                             case API_ACTION_HIDE:
  377.  
  378.                                                 DeleteTMObject(handle, "dock1");
  379.                                                 break;
  380.  
  381.                                             case API_ACTION_SHOW:
  382.  
  383.                                                 struct Screen *screen;
  384.  
  385.                                                 if (screen = LockPubScreen(nextMsg->api_Global->F_ScrnName)) {
  386.  
  387.                                                     dock[0].ti_Data = nextMsg->api_Global->F_ScrnName;
  388.                                                     dock[1].ti_Data = (dockX == ~0) ? screen->Width         : dockX;
  389.                                                     dock[2].ti_Data = (dockY == ~0) ? screen->BarHeight + ((screen->BitMap.Depth == 1) ? 2 : 1) : dockY;
  390.  
  391.                                                     UnlockPubScreen(NULL, screen);
  392.                                                 }
  393.  
  394.                                                 CreateTMObjectTagList(handle, "dock1", TMOBJTYPE_DOCK, dock);
  395.  
  396.                                                 break;
  397.  
  398.                                             default:
  399.  
  400.                                                 nextMsg->api_Error = API_ERROR_UNKNOWN;
  401.                                         }
  402.                                         break;
  403.  
  404.                                     default:
  405.  
  406.                                         nextMsg->api_Error = API_ERROR_UNKNOWN;
  407.                                 }
  408.                             }
  409.                         }
  410.  
  411.                         ReplyMsg((struct Message *)apiMsg);
  412.  
  413.                     } while (apiMsg = (struct APIMessage *)GetMsg(replyPort));
  414.  
  415.                 } while (active);
  416.             }
  417.         }
  418.  
  419.         DeleteMsgPort(replyPort);
  420.     }
  421. }
  422.  
  423.  
  424. ///
  425. /// "misc"
  426.  
  427. /* --------------------------------- xsprintf ----------------------------------
  428.  
  429.  sprintf frontend (malloc buffer); limited to string insertion into string
  430.  
  431. */
  432.  
  433. char *
  434. xsprintf(mask, var)
  435.  
  436. char *mask, *var;
  437. {
  438.     char *buffer;
  439.  
  440.     if (buffer = malloc(strlen(mask) + strlen(var)))
  441.         sprintf(buffer, mask, var);
  442.  
  443.     return(buffer);
  444. }
  445.  
  446. ///
  447. /// "ARexx"
  448.  
  449. /* ---------------------------------- SendRexxCommand -------------------------
  450.  
  451.  Send ARexx message & wait for answer. Return pointer to result or NULL.
  452.  
  453. */
  454.  
  455. ULONG *
  456. SendRexxCommand(port, cmd, replyPort, buffer)
  457.  
  458. char   *cmd, *port, *buffer;
  459. struct MsgPort *replyPort;
  460. {
  461.     struct MsgPort *rexxport;
  462.  
  463.     Forbid();
  464.  
  465.     if (rexxport = FindPort(port)) {
  466.  
  467.         struct RexxMsg *rexxMsg, *answer;
  468.  
  469.         if (rexxMsg = CreateRexxMsg(replyPort, NULL, NULL)) {
  470.  
  471.             if (rexxMsg->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {
  472.  
  473.                 static ULONG result;
  474.  
  475.                 rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;
  476.  
  477.                 PutMsg(rexxport, &rexxMsg->rm_Node);
  478.  
  479.                 do {
  480.                     
  481.                     WaitPort(replyPort);
  482.  
  483.                     if (answer = (struct RexxMsg *)GetMsg(replyPort))
  484.                         result = answer->rm_Result1;
  485.  
  486.                 } while (!answer);
  487.  
  488.                 Permit();
  489.  
  490.                 if (answer->rm_Result1 == RC_OK) {
  491.  
  492.                     if (answer->rm_Result2) {
  493.  
  494.                         if (buffer)
  495.                             strcpy(buffer, (char *)answer->rm_Result2);
  496.  
  497.                         DeleteArgstring((char *)answer->rm_Result2);
  498.                     }
  499.                 }
  500.  
  501.                 DeleteArgstring((char *)ARG0(answer));
  502.  
  503.                 DeleteRexxMsg(answer);
  504.  
  505.                 return(&result);
  506.             }
  507.         }
  508.     }
  509.  
  510.     Permit();
  511.  
  512.     return(NULL);
  513. }
  514.  
  515. ///
  516.